package seqlist.stack_queue.queue.impl;

import seqlist.stack_queue.queue.MyQueue;

import java.util.NoSuchElementException;

/**
 * @author yuisama
 * @date 2023/03/22 21:07
 **/
public class LoopQueue<E> implements MyQueue<E> {
    private Object[] data;
    // head一定指向当前循环队列的队首元素
    private int head;
    // tail一定指向当前循环队列的队尾元素的下一个位置
    private int tail;
    // 当前有效元素的个数
    private int size;

    public LoopQueue(int size) {
        // 浪费当前数组的一个位置来判断空还是满
        this.data = new Object[size + 1];
    }
    @Override
    public void offer(E val) {
        if (isFull()) {
            throw new IllegalStateException("queue is full!cannot offer");
        }
        data[tail] = val;
        tail = (tail + 1) % data.length;
        size ++;
    }

    @Override
    public E poll() {
        if (isEmpty()) {
            throw new NoSuchElementException("queue is empty!cannot poll");
        }
        E val = (E) data[head];
        head = (head + 1) % data.length;
        size --;
        return val;
    }

    @Override
    public E peek() {
        if (isEmpty()) {
            throw new NoSuchElementException("queue is empty!cannot peek!");
        }
        E val = (E) data[head];
        return val;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("front [");
        // 最后一个有效元素的索引是多少？
        int lastIndex = tail == 0 ? data.length - 1 : tail - 1;
        for (int i = head; i != tail;) {
            sb.append(data[i]);
            if (i != lastIndex) {
                sb.append(", ");
            }
            i = (i + 1) % data.length;
        }
        sb.append("] tail");
        return sb.toString();
    }

    public int size() {
        return this.size;
    }

    private boolean isEmpty() {
        return head == tail;
    }

    private boolean isFull() {
        return (tail + 1) % data.length == head;
    }
}